import _thread
import smtplib
import webbrowser
from email.header import Header
from email.mime.text import MIMEText
from tkinter import *
from tkinter import filedialog, messagebox
import configparser #配置文件模块

import pandas as pd



def getConfig(section,key):
    config = configparser.ConfigParser()
    #获取配置文件的真实路径
    path ='config.ini' 
    #print("获取配置文件的真实路径为："+path)
    config.read(path,encoding="utf-8")
    return config.get(section,key)

class App:
    # 全部
    all_info: int = 0
    # 发送失败
    err_info: int = 0
    # 发送成功
    suc_info: int = 0
    # 当前数据
    t: pd.DataFrame = None
    # 表示正在执行的邮件发送线程的数量
    counter: int = 0
    # html模板，为了防止打包打不进去，干脆写进来了
    html: str = """""" 

    def __init__(self, _root):
        self.root = _root
        self.center_window()
        # 布局
        # line_0
        self.path = StringVar()
        # self.path.set("请将路径复制到此框或通过右边按钮选择路径")
        # self.path.set("D:/code2/auto/工资条.xlsx")
        self.path_e = Entry(self.root, textvariable=self.path, width=72)
        self.path_e.grid(row=0, column=0, columnspan=3, padx=5, pady=5)
        self.path_button = Button(self.root, text='选择路径', command=self.select_path)
        self.path_button.grid(row=0, column=3, padx=5, pady=5)

        # line_1
        self.info = Listbox(self.root, width=82)
        self.info.grid(row=1, column=0, padx=5, pady=5, columnspan=4)

        # line_2
        self.show_table_b = Button(self.root, text='预览文件', command=self.show_table)
        self.show_table_b.grid(row=2, column=1, padx=5, pady=5)
        self.send_email_b = Button(self.root, text='发送邮件', command=self.send)
        self.send_email_b.grid(row=2, column=2, padx=5, pady=5, sticky='w')

        # line_3
        self.msg = StringVar()
        self.msg.set('邮件发送状态')
        self.msb_l = Label(self.root, textvariable=self.msg)
        self.msb_l.grid(row=3, column=0, columnspan=3, padx=5, pady=5, sticky='w')
        # # 获取html模板
        # with open('a.html', 'r') as f:
        #     self.html = f.read()
        # print(self.getConfigValue('title'))   

    def select_path(self):
        path_ = filedialog.askopenfilename(title='打开工资表', filetypes=[('Excel', '*.xlsx')])
        # 如果要打开旧版本Excel文件，可以将下面这一行取消注释。顺便将上面一行注释掉。也可以自己写完整的文件后缀。
        # path_ = filedialog.askopenfilename(title='打开工资表')
        if path_ != "":
            self.path.set(path_)

    # 窗口居中，有bug，在电脑设置了“‘缩放与布局-->更改文本、应用等项目的大小’”不为100%时会有偏差。跟分辨率和像素有关，无心解决
    def center_window(self, w=600, h=280):
        ws = self.root.winfo_screenwidth()
        hs = self.root.winfo_screenheight()
        x = (ws // 2) - (w // 2)
        y = (hs // 2) - (h // 2)
        self.root.geometry(f'{w}x{h}+{x}+{y}')

    # 就是通过浏览器读取一下Excel信息，应用空间很小，估计只有在电脑上没有安装Excel才能用到吧~
    def show_table(self):
        # 读Excel
        if self.get_data():
            return
        self.all_info = self.t.index.size
        self.t.to_html('a.html')
        webbrowser.open('a.html')

    # 读取并发送。
    def send(self):
        # 读Excel
        if self.get_data():
            return
        self.all_info = self.t.index.size
        # 防止按钮被点坏了
        self.send_email_b['state'] = 'disable'
        for index, row in self.t.iterrows():
            # 多线程防止界面假死
            _thread.start_new_thread(self.send_email, (row.values,))

    # 发送邮件并更新状态
    def send_email(self, data: list):  
        self.counter += 1
        # 替换模板内容
        html = ''
        # for index, item in enumerate(html):
        #     print(item)
        for index, item in enumerate(data):
            # html = html.replace('{' + str(index) + '}', str(item))
            html= html+self.t.columns[index]+":"+str(item)+"<br/>"
        receiver = data[0]
        print(html)
        # 发送邮箱的用户名和授权码（不是登录邮箱的密码）
        username = getConfig('mail','username')
        password = getConfig('mail','password')
        host = getConfig('mail','host')
        port = getConfig('mail','port')

        # 邮件主题
        mail_title = getConfig('mail','mailtitle')

        # 邮件内容, 格式, 编码
        message = MIMEText(html, 'html', 'utf-8')
        message['From'] = u'<' + username + '>'
        message['To'] = receiver
        message['Subject'] = Header(mail_title, 'utf-8') 
        try:
            smtp = smtplib.SMTP_SSL(host,port)
            # smtp.connect(':465')
            smtp.login(username, password)
            smtp.sendmail(username, receiver, message.as_string())
            smtp.quit()
            state = '成功'
            self.suc_info += 1
        except smtplib.SMTPException as e:
            state = str(e)
            self.err_info += 1
        # 添加状态
        self.info.insert('end', data[1].ljust(10, '－') + receiver.ljust(25, '-') + state)
        self.counter -= 1
        if self.counter == 0:
            self.send_email_b['state'] = 'normal'
        # 更新信息
        self.msg.set(
            f'邮件发送状态：共计 {self.all_info} 条信息，'
            f'已发送{self.suc_info + self.err_info}条，'
            f'剩余{self.all_info - self.suc_info - self.err_info}条，'
            f'其中成功发送{self.suc_info}条,'
            f'失败{self.err_info}条')

    def get_data(self):
        try:
            self.t = pd.read_excel(self.path.get())
            self.t.fillna('', inplace=True)
            return False
        except Exception as e:
            messagebox.showerror('出现异常', str(e))
            return True


if __name__ == '__main__': 
    # 写的不规范，但是无奈不知道规范的怎么写~
    root = Tk()
    # 设置全局字体，在四处寻求无果后于百度知道找到了一位大佬在2011年写出的答案
    root.option_add('*Font', 'Fira 10')
    root.title(getConfig('config','title')) 
    root.resizable(0, 0)
    App(root)
    root.mainloop()